package com.yeyks.commonReference.service.consumer.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yeyks.common.base.Arguments;
import com.yeyks.common.constants.ConfigKey;
import com.yeyks.common.constants.MessageTemplate;
import com.yeyks.common.constants.OrderStatus;
import com.yeyks.common.dto.UserInfoDTO;
import com.yeyks.common.em.MessageNoticeType;
import com.yeyks.common.em.ResponseStatus;
import com.yeyks.common.em.UserCouponInfoStatus;
import com.yeyks.common.em.consumer.UserInviteRelationTypeEnum;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.param.DownloadUserByParam;
import com.yeyks.common.result.UserStatisticalResult;
import com.yeyks.common.result.order.UserOrderResult;
import com.yeyks.common.result.screen.DataScreenUserResult;
import com.yeyks.common.result.user.UserDetailResult;
import com.yeyks.common.utils.*;
import com.yeyks.common.utils.base.PhoneUtil;
import com.yeyks.commonReference.append.activity.ActivityNewUserTaskService;
import com.yeyks.commonReference.append.app.TokenService;
import com.yeyks.commonReference.append.sms.SmsService;
import com.yeyks.commonReference.append.yedun.YeDunService;
import com.yeyks.commonReference.service.config.ConfigService;
import com.yeyks.commonReference.service.consumer.MessageNoticeTemplateService;
import com.yeyks.commonReference.service.consumer.UserCouponInfoService;
import com.yeyks.commonReference.service.order.OrderHeadService;
import com.yeyks.commonReference.service.user.UserCommissionService;
import com.yeyks.consumer.dal.dao.UserInfoMapper;
import com.yeyks.consumer.dal.domain.UserCouponInfo;
import com.yeyks.consumer.dal.domain.UserInfo;
import com.yeyks.consumer.dal.domain.UserInviteRelation;
import com.yeyks.consumer.dal.domain.UserLoginHistory;
import com.yeyks.consumer.dto.BankBindDTO;
import com.yeyks.consumer.dto.UserInfoResult;
import com.yeyks.consumer.param.UserInfo.*;
import com.yeyks.consumer.service.MessageNoticeService;
import com.yeyks.consumer.service.UserInfoService;
import com.yeyks.consumer.service.UserInviteRelationService;
import com.yeyks.consumer.service.UserLoginHistoryService;
import com.yeyks.consumer.vo.UserInfoLoginVo;
import com.yeyks.order.dal.domain.OrderHead;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * <p>
 * C端用户表 服务实现类
 * </p>
 *
 * @author yun
 * @since 2019-06-25
 */
@Slf4j
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserCouponInfoService userCouponService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private MessageNoticeService noticeService;
    @Autowired
    private MessageNoticeTemplateService templateService;
    @Autowired
    private UserInviteRelationService userInviteRelationService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private UserCommissionService userCommissionService;
    @Autowired
    private UserLoginHistoryService userLoginHistoryService;
    @Autowired
    private OrderHeadService orderHeadService;
    @Autowired(required = false)
    private YeDunService yeDunService;
    @Autowired
    private ActivityNewUserTaskService activityNewUserTaskService;

    /**
     * 通过手机号查询用户信息
     *
     * @param phone
     * @return
     */
    @Override
    public UserInfo selectUseInfoPhone(String phone) {
        return baseMapper.selectOne(
                new QueryWrapper<UserInfo>()
                        .eq(UserInfo.PHONE, phone)
                        .eq(UserInfo.STATUS, 1)
                        .eq(UserInfo.IS_DEL, 1)
                        .last("limit 1")
        );
    }

    /**
     * 通过id查询用户信息
     */
    @Override
    public UserInfo getById(Integer id) {
        return baseMapper.selectOne(
                new QueryWrapper<UserInfo>()
                        .eq(UserInfo.ID, id)
                        .eq(UserInfo.STATUS, 1)
                        .eq(UserInfo.IS_DEL, 1)
                        .last("limit 1")
        );
    }

    /**
     * 根据邀请码查询用户
     * @param inviteCode
     * @return
     */
    @Override
    public UserInfo getByInviteCode(String inviteCode) {
        return baseMapper.selectOne(
                new QueryWrapper<UserInfo>()
                        .eq(UserInfo.INVITE_CODE, inviteCode)
                        .eq(UserInfo.IS_DEL, 1)
                        .last("limit 1")
        );
    }

    /**
     * 获取用户手机号
     *
     * @param id
     * @return
     */
    @Override
    public String getPhoneById(Integer id) {
        UserInfo userInfo = baseMapper.selectById(id);
        return null == userInfo ? null : userInfo.getPhone();

    }

    @Override
    public UserInfo createUser(UserInfo userInfo) {
        if (Pattern.matches(configService.getValue(ConfigKey.DISABLE_PHONE_REGISTRATION_RULES), userInfo.getPhone())) {
            throw new ServiceException("该手机号段禁止注册");
        }
        Date date = new Date();
        userInfo.setGmtCreate(date);
        userInfo.setGmtModified(date);
        int res = baseMapper.insert(userInfo);
        if (res != 1) {
            log.info("创建用户异常");
        }
        userInfo.setInviteCode(InvateCode.toSerialCode(userInfo.getId()));
        baseMapper.update(null, new UpdateWrapper<UserInfo>()
                .set(UserInfo.INVITE_CODE, userInfo.getInviteCode())
                .eq(UserInfo.ID, userInfo.getId())
        );
        //给注册用户发送短信，内容为自己密码
        if (!smsService.sendPwcSms(userInfo.getPhone(), userInfo.getPassword())) {
            log.info("给注册用户发送短信失败");
        }
        //给新用户发两张10元优惠券,v3.5
//        userCouponService.createNewCoupon(userInfo.getId());
        return userInfo;
    }

    private List<Integer> logTypeList = CollectionUtil.newArrayList(4,5);

    //用户登录
    @Override
    public UserInfoLoginVo login(UserInfoLoginParam param) {
        try {
            if (Objects.nonNull(param.getType()) && !CollectionUtil.contains(logTypeList, param.getType())) {
                throw new ServiceException("非法参数");
            }
            String code = param.getCode();
            String phone = param.getPhone();
            String password = param.getPassword();
            String sourceType = param.getSourceType();
            String unionId = param.getUnionId();
            UserInfo userInfo;
            UserInfoLoginVo userInfoLoginVo = null;
            UserLoginHistory userLoginHistory = new UserLoginHistory();
            userLoginHistory.setResult("成功");
            userLoginHistory.setType(param.getSourceType());
            userLoginHistory.setIp(param.getIp());
            userLoginHistory.setMac(param.getMac());
            userLoginHistory.setDeviceId(param.getDeviceId());
            try {
                if (Objects.nonNull(param.getAccessCode()) && Objects.nonNull(param.getToken())) {
                    //一键登录
                    phone = yeDunService.getPhone(param.getAccessCode(), param.getToken());
                    if (Objects.isNull(phone)) {
                        throw new ServiceException("一键登录失败");
                    }
                    param.setPhone(phone);
                    // 查找用户的所有信息
                    userInfo = selectUseInfoPhone(phone);
                    if (Objects.nonNull(userInfo)) {
                        userInfoLoginVo = packLoginResult(userInfo);
                    } else {
                        userInfo = getUserInfo(sourceType, phone, null);
                        createUser(userInfo);
                        userInfoLoginVo = packLoginResult(userInfo);
                    }
                }else if (Objects.nonNull(param.getUserId()) && StrUtil.isBlank(password)) {
                    try {
                        UserInfoPhoneLoginParam userInfoPhoneLoginParam = BeanUtil.toBean(param, UserInfoPhoneLoginParam.class);
                        userInfo = phoneLoginReturn(userInfoPhoneLoginParam);
                        userInfoLoginVo = packLoginResult(userInfo);
                    } catch (Exception e) {
                        //验证码登录
                        userInfoLoginVo = PhoneLogin(code, phone, sourceType, null);
                    }
                } else if (StrUtil.isNotBlank(unionId)) {
                    //微信登录
                    userInfo = getUserInofByUnionId(unionId);
                    if (Objects.isNull(userInfo)) {
                        if (StrUtil.isBlank(phone)) {
                            throw new ServiceException(ResponseStatus.RS_WECHAT_NO_BINDING.getCode(), ResponseStatus.RS_WECHAT_NO_BINDING.getMsg());
                        }
                        userInfoLoginVo = PhoneLogin(code, phone, sourceType, unionId);
                    } else {
                        userInfoLoginVo = packLoginResult(userInfo);
                    }
                } else if (StrUtil.isNotBlank(code)) {
                    //验证码登录
                    userInfoLoginVo = PhoneLogin(code, phone, sourceType, null);
                } else {
                    //密码登录
                    checkParamPhonePwd(phone, password);
                    //加密密码
                    password = AppServerUtil.getEncodePassword(password);
                    //用户的话使用手机号密码登陆
                    userInfo = selectUseInfoPhone(phone);
                    if (userInfo == null) {
                        throw new ServiceException("该用户不存在");
                    }
                    if (!password.equals(userInfo.getMd5Password())) {
                        throw new ServiceException("密码输入有误");
                    }
                    userInfoLoginVo = packLoginResult(userInfo);
                }
                return userInfoLoginVo;
            } catch (Exception e) {
                userLoginHistory.setResult("失败");
                throw e;
            } finally {
                //创建新手任务v4.3.0
                try {
                    if(Objects.equals(userInfoLoginVo.getUser_info().getNewFlag(),0)){
                        activityNewUserTaskService.createTask(userInfoLoginVo.getUser_info().getId());
                    }
                } catch (Exception e) {
                    log.error("创建新手任务失败:{}",e.getMessage());
                }
                //记录登录
                if (Objects.nonNull(userInfoLoginVo) && Objects.nonNull(userInfoLoginVo.getUser_info())) {
                    userLoginHistory.setUserId(userInfoLoginVo.getUser_info().getId());
                    userLoginHistory.setPhone(userInfoLoginVo.getUser_info().getPhone());
                }
                userLoginHistoryService.saveByIndependentTransaction(userLoginHistory);
            }
        } catch (Exception e) {
            UserInfo userInfo = getOne(
                    new QueryWrapper<UserInfo>()
                            .eq(UserInfo.PHONE, param.getPhone())
                            .last("limit 1")
            );
            if (Objects.nonNull(userInfo) && (Objects.equals(userInfo.getIsDel(), 0) || Objects.equals(userInfo.getStatus(), 0))) {
                throw new ServiceException("您的账号异常已被锁定，暂时无法登录");
            }
            throw e;
        }
    }

    //用户登录 v3.7.1
    @Override
    public UserInfoLoginVo loginApp(UserInfoLoginParam param) {
        UserInfoLoginVo userInfoLoginVo = login(param);
        //发放新人券并发放0元佣金
        userCommissionService.saveZeroCommission(param.getPhone(), param.getDeviceId());
        return userInfoLoginVo;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserInfoLoginVo oneClickLogin(UserInfoOneClickLoginParam param) {
        UserInfoLoginParam userInfoLoginParam = BeanUtil.toBean(param, UserInfoLoginParam.class);
        UserInfoLoginVo userInfoLoginVo = loginApp(userInfoLoginParam);
        return userInfoLoginVo;
    }


    private UserInfoLoginVo PhoneLogin(String code, String phone, String sourceType, String unionId) {
        UserInfo userInfo;
        checkParamPhone(phone);
        if (smsService.verifySmsForSignup(phone, code)) {
            // 查找用户的所有信息
            userInfo = selectUseInfoPhone(phone);
            if (Objects.nonNull(userInfo)) {
                if (StrUtil.isNotBlank(unionId)) {
                    boolean update = update(
                            new UpdateWrapper<UserInfo>()
                                    .set(UserInfo.UNION_ID, unionId)
                                    .eq(UserInfo.ID, userInfo.getId())
                    );
                    if (!update) {
                        throw new ServiceException("用户微信绑定失败");
                    }
                }
                return packLoginResult(userInfo);
            } else {
                userInfo = getUserInfo(sourceType, phone, null);
                if (StrUtil.isNotBlank(unionId)) {
                    userInfo.setUnionId(unionId);
                }
                createUser(userInfo);
                return packLoginResult(userInfo);
            }
        } else {
            throw new ServiceException("验证码无效");
        }
    }

    private UserInfo getUserInofByUnionId(String unionId) {
        return baseMapper.selectOne(
                new QueryWrapper<UserInfo>()
                        .eq(UserInfo.UNION_ID, unionId)
                        .last("limit 1")
        );
    }

    private UserInfoLoginVo packLoginResult(UserInfo userInfo) {
        UserInfoDTO userInfoDTO = ObjectConvertUtil.convertObject(userInfo, UserInfoDTO.class);
        userInfoDTO.setVipStatus(userInfo.getIsVip());
        if (ArgumentsCheckUtil.strIsNull(userInfo.getPassword())) {
            userInfoDTO.setPassword(null);
        } else {
            userInfoDTO.setPassword("yyks2019");
        }
        // 用户ID生成Token
        String token = getTokenByUseId(userInfo.getId());
        // 生成结果
        Map<String, Object> res = new HashMap<>();
        res.put("user_info", userInfoDTO);
        res.put("token", token);
        return new UserInfoLoginVo().setUser_info(userInfoDTO).setToken(token);
    }

    private UserInfo getUserInfo(String sourceType, String phone, Integer parentId) {
        UserInfo userInfo = new UserInfo();
        userInfo.setNickname(Utility.randomName());
        String password = Utility.randomPwd();
        userInfo.setPassword(password);
        userInfo.setMd5Password(AppServerUtil.getEncodePassword(password));
        userInfo.setType(1);
        userInfo.setPhone(phone);
        userInfo.setValid(true);
        userInfo.setStatus(1);
        userInfo.setSourceType(sourceType);
        userInfo.setIsVip(0);
        userInfo.setIsDel(1);
        userInfo.setParentId(parentId);
        userInfo.setNewFlag(0);
        return userInfo;
    }

    private void checkParamPhone(String phone) {
        if (ArgumentsCheckUtil.isEmpty(phone)) {
            throw new ServiceException("手机号不能为空");
        }
        if (!TextValidator.MOBILE.boolCheck(phone)) {
            throw new ServiceException("手机号格式非法");
        }
    }

    private void checkParamPwd(String password) {
        if (ArgumentsCheckUtil.isEmpty(password)) {
            throw new ServiceException("密码输入为空");
        }
        if (password.length() < 6 || password.length() > 16) {
            throw new ServiceException("密码的有效长度为6-16位");
        }
    }

    private void checkParamPhoneUseId(String phone, Integer userId) {
        checkParamPhone(phone);
        if (ArgumentsCheckUtil.isNullOrZero(userId)) {
            throw new ServiceException("分享人id不能为空");
        }
    }

    private void checkParamPhonePwd(String phone, String password) {
        checkParamPhone(phone);
        checkParamPwd(password);
    }

    @Override
    public List<UserInfoResult> queryPageList(UserInfoQueryParam userInfoQueryParam) {
        return baseMapper.queryList(userInfoQueryParam);
    }

    @Override
    public int queryListCount(UserInfoQueryParam userInfoQueryParam) {
        return baseMapper.queryListCount(userInfoQueryParam);
    }

    private void payMessageNotice(Integer userId, Integer payAmount, Integer price, int count) {
        try {
            String payAmountStr = FormatUtils.fenToYuan(payAmount);
            String amount = FormatUtils.fenToYuan(price);
            Map<String, Object> params = new HashMap<>();
            params.put("payAmount", payAmountStr);
            params.put("amount", amount);
            params.put("count", count);
            Map<String, String> map = templateService.commonValue(params, MessageTemplate.PAY_COUPON);
            noticeService.activieyCreateAndSave(map, userId, MessageNoticeType.activity_coupon.value());
        } catch (Exception e) {
            log.error("分享充值消息写入异常{}", e.getLocalizedMessage());
            e.printStackTrace();
        }
    }

    /**
     * 用户设置头像
     *
     * @param id
     * @param avatar
     * @return
     */
    @Override
    public Integer updateAvatar(Integer id, String avatar) {
        return baseMapper.updateAvatar(id, avatar);
    }

    /**
     * 增加用户，并返回用户id
     *
     * @param userInfo
     */
    @Override
    public void insertReturnId(UserInfo userInfo) {
        Date date = new Date();
        userInfo.setGmtCreate(date);
        userInfo.setGmtModified(date);
        baseMapper.insert(userInfo);
    }

    /**
     * 通过用户id，修改用户密码
     *
     * @param id
     * @param password
     * @return
     */
    @Override
    public Integer modifyPasswordById(Integer id, String password) {
        return baseMapper.modifyPasswordById(id, password);
    }

    /**
     * 分享后用户通过手机号注册
     *
     * @param param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean phoneLogin(UserInfoPhoneLoginParam param) {
        phoneLoginReturn(param);
        return true;

    }

    private UserInfo phoneLoginReturn(UserInfoPhoneLoginParam param) {
        String phone = param.getPhone();
        Integer userId = param.getUserId();
        String sourceType = param.getSourceType();
        String code = param.getCode();
        Integer type = Objects.nonNull(param.getType()) ? param.getType() : UserInviteRelationTypeEnum.PROMOTION.getValue();
        checkParamPhoneUseId(phone, userId);
        if (!smsService.verifySmsForSignup(phone, code)) {
            throw new ServiceException("验证码错误");
        }
        //通过该手机号查询该用户是否存在
        UserInfo userInfo = selectUseInfoPhone(phone);
        if (userInfo != null) {
            log.info("该手机号已经存在{}", phone);
            throw new ServiceException("该手机号已注册");
        }
        userInfo = getUserInfo(sourceType, phone, userId);
        //保存用户的信息
        createUser(userInfo);
        //保存分享的关系
        userInviteRelationService.createUserInviteRelation(userInfo.getId(), userId, type);
        //记录佣金注册记录信息 v3.7.1
        userCommissionService.messageNoticeZero(userInfo.getId(), userId);
        return userInfo;
    }


    private void messageNotice(String phone, Integer price, int count, Integer userId) {
        try {
            String amount = FormatUtils.fenToYuan(price);
            Map<String, Object> params = new HashMap<>();
            params.put("phone", PhoneUtil.replace(phone));
            params.put("amount", amount);
            params.put("count", count);
            Map<String, String> map = templateService.commonValue(params, MessageTemplate.INVATE_COUPON);
            noticeService.activieyCreateAndSave(map, userId, MessageNoticeType.activity_coupon.value());
        } catch (Exception e) {
            log.error("分享有礼消息写入异常{}", e.getLocalizedMessage());
            e.printStackTrace();
        }
    }

    private UserCouponInfo getUserCouponInfo(Integer userId, Integer couponId, Integer duration) {
        UserCouponInfo userCouponInfo = new UserCouponInfo();
        userCouponInfo.setCouponId(couponId);
        userCouponInfo.setUserId(userId);
        userCouponInfo.setUsed(UserCouponInfoStatus.NO_USE.value());
        if (duration == null || duration == 0) {
            //180天
            duration = 180;
        }
        Date date = DateUtils.afterDaysToDate(new Date(), Long.valueOf(duration));
        userCouponInfo.setOverTime(date);
        Date nowDate = new Date();
        userCouponInfo.setGmtModified(nowDate);
        userCouponInfo.setGmtCreate(nowDate);
        return userCouponInfo;
    }

    /**
     * 通过用户id获取token
     *
     * @param userId
     * @return
     */
    @Override
    public String getTokenByUseId(Integer userId) {
        return tokenService.createToken(String.valueOf(userId));
    }

    /**
     * 通过token获取用户信息
     *
     * @param token
     * @return
     */
    @Override
    public UserInfo tokenUserInfo(String token) {
        UserInfo userInfo = null;
        try {
            String userId = tokenService.getUserId(token);
            userInfo = baseMapper.selectById(userId);
        } catch (ServiceException e) {
            throw new ServiceException(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.info("通过用户token获取用户失败，token=" + token + "，错误信息：" + e.getMessage());
        }
        if (userInfo == null) {
            log.info("该用户不存在，token={}", token);
            throw new ServiceException("该用户不存在");
        }
        return userInfo;
    }

    /**
     * 通过邀请码获取该用户是否存在
     *
     * @param code
     * @return
     */
    @Override
    public UserInfo selectUserByCode(String code) {
        return baseMapper.selectUserByCode(code);

    }

    @Override
    public int updateUserInfo(UserInfo userInfo) {
        userInfo.setGmtModified(new Date());
        return baseMapper.updateById(userInfo);
    }

    /**
     * 判断用户是否需要绑卡
     *
     * @param userInfo
     * @return
     */
    @Override
    public Boolean isBind(UserInfo userInfo) {
        boolean flag = false;
        try {
            String payAccount = userInfo.getPayAccount();
            if (payAccount == null) {
                flag = true;
            }
        } catch (Exception e) {
            log.error("判断用户是否需要绑卡异常{}", e.getLocalizedMessage());
            e.printStackTrace();
            flag = true;
        }
        return flag;
    }

    /**
     * 用户绑定银行卡
     *
     * @param userInfo
     * @param bankCard
     * @param bankName
     * @param branchName
     * @param userName
     * @return
     */
    @Override
    public Boolean bankCard(UserInfo userInfo, String bankCard, String bankName, String branchName, String userName) {
        try {
            Map<String, String> map = new HashMap<>();
            map.put("bankCard", bankCard);
            map.put("bankName", bankName);
            map.put("userName", userName);
            map.put("branchName", branchName);
            userInfo.setPayAccount(JSONObject.toJSONString(map));
            userInfo.setGmtModified(new Date());
            return baseMapper.updateById(userInfo) == 1;
        } catch (Exception e) {
            log.error("用户绑定银行卡异常{}", e.getLocalizedMessage());
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取用户绑卡信息
     *
     * @param userInfo
     * @return
     */
    @Override
    public BankBindDTO bankCardInfo(UserInfo userInfo) {
        BankBindDTO bankBindDTO = new BankBindDTO();
        String payAccount = userInfo.getPayAccount();
        if (Arguments.strNotNull(payAccount)) {
            JSONObject jsonObject = JSONObject.parseObject(payAccount);
            bankBindDTO.setBankCard((String) jsonObject.get("bankCard"));
            bankBindDTO.setBankName((String) jsonObject.get("bankName"));
            bankBindDTO.setUserName((String) jsonObject.get("userName"));
            bankBindDTO.setBranchName((String) jsonObject.get("branchName"));
            return bankBindDTO;
        }
        log.info("该用户并未绑卡userId = {}", userInfo.getId());
        return bankBindDTO;
    }

    /**
     * 查询过去n天新增用户数（查询到的数据是n+1条，包括今天）
     *
     * @param day
     * @return
     */
    @Override
    public List<UserStatisticalResult> statDay(Integer day) {
        if (null == day || 0 == day) {
            day = 6;
        }
        Map<String, Object> map = Maps.newHashMap();
        LocalDate now = LocalDate.now().plusDays(1);
        map.put("orderStart", DateUtils.toDate(now.minusDays(day)));
        map.put("orderEnd", DateUtils.toDate(now));
        List<UserStatisticalResult> resultList = baseMapper.statDay(day);
        return resultList;
    }

    @Override
    public String checkCode(UserInofCheckCodeParam param) {
        String code = param.getCode();
        String phone = param.getPhone();
        String inviteId = param.getInviteId();
        checkParamPhone(phone);
        boolean flag = smsService.verifySmsForSignup(phone, code);
        String token = null;
        if (flag) {
            //获取邀请人信息
            UserInfo parentUserInfo = selectUserByCode(inviteId);
            if (Objects.isNull(parentUserInfo)) {
                throw new ServiceException("邀请码有误");
            }
            //通过该手机号查询该用户是否存在
            UserInfo userInfo = selectUseInfoPhone(phone);
            if (userInfo != null) {
                token = tokenService.createToken(String.valueOf(userInfo.getId()));
            } else {
                userInfo = getUserInfo(null, phone, parentUserInfo.getId());
                createUser(userInfo);
//                sendMessage(phone);
                token = tokenService.createToken(String.valueOf(userInfo.getId()));
                //绑定用户推荐人
                userInviteRelationService.createUserInviteRelation(userInfo.getId(), parentUserInfo.getId(), UserInviteRelationTypeEnum.PROMOTION.getValue());
                //记录佣金注册记录信息 v3.7.1
                userCommissionService.messageNoticeZero(userInfo.getId(), parentUserInfo.getId());
            }
        } else {
            throw new ServiceException("验证码输入有误");
        }
        return token;
    }

    @Override
    public List<UserInfo> queryUserByParentIdPage(UserInfoQueryByParentIdParam parentIdParam) {

        PageHelper.startPage(parentIdParam.getPageNum(), parentIdParam.getPageSize());
        List<UserInfo> userInfoList = baseMapper.queryUserByParentIdPage(parentIdParam);
        if (!CollectionUtils.isEmpty(userInfoList)) {
            return userInfoList;
        }
        return null;
    }

    @Override
    public List<UserInfo> queryChildUser(List<Integer> parentIds) {
        return baseMapper.queryChildUser(parentIds);
    }

    @Override
    public Integer queryUserByParentIdCount(UserInfoQueryByParentIdParam parentIdParam) {

        return baseMapper.queryUserByParentIdCount(parentIdParam);
    }

    /**
     * 用户详情
     *
     * @param userId
     * @return
     */
    @Override
    public UserDetailResult userDetail(Integer userId) {
        Arguments.intIsNull(userId, "用户id不能为空");
        UserInfo userInfo = baseMapper.selectById(userId);
        Arguments.beanIsNull(userInfo, "该用户还未注册");
        UserDetailResult userDetailResult = BeanUtil.toBean(userInfo, UserDetailResult.class);
        userDetailResult.setUserId(userInfo.getId());
        userDetailResult.setCreateTime(userInfo.getGmtCreate());
        //获取邀请人数(0元推广)
        userDetailResult.setInviteUserCount(userInviteRelationService.getInviteUserCount(Lists.newArrayList(UserInviteRelationTypeEnum.PROMOTION.getValue(), UserInviteRelationTypeEnum.MAKER.getValue()), userId));
        //用户最近消费时间(c2b)
        userDetailResult.setLastOrderTime(orderHeadService.lastOrderTime(userId, 0));
        //累计消费金额(c2b订单完成)
        UserOrderResult userOrderResult = orderHeadService.selectUserTotalAmount(userId, 0);
        userDetailResult.setC2bTotalAmount(userOrderResult.getOrderTotalAmount());
        //优惠券使用次数
        userDetailResult.setCouponUseCount(userCouponService.selectCouponUseCountByUserId(userId));
        //累计下单数(c2b订单完成)
        userDetailResult.setC2bOrderCount(userOrderResult.getOrderCount());
        //客单价
        if (0 != userDetailResult.getC2bOrderCount()) {
            userDetailResult.setC2bAverageAmount(userDetailResult.getC2bTotalAmount() / userDetailResult.getC2bOrderCount());
        }
        if (null == userDetailResult.getC2bAverageAmount()) {
            userDetailResult.setC2bAverageAmount(0);
        }
        return userDetailResult;
    }

    @Override
    public List<UserInfoResult> queryDownloadUserByParam(DownloadUserByParam param) {
        List<UserInfo> list = Lists.newArrayList();
        switch (param.getType()) {
            case "0":
                list = baseMapper.selectList(new QueryWrapper<UserInfo>().eq(UserInfo.IS_DEL, 1)
                        .eq(UserInfo.STATUS, 1));
                break;
            case "1":
                //时间戳转换
                if (param.getDissipate() == null || param.getDissipate() == 0) {
                    throw new ServiceException("最近消费时间不能为空");
                }
                String beforeTime = DateUtils.stampToYMDStr(param.getDissipate());
                List<OrderHead> orderHeadList = orderHeadService.list(new QueryWrapper<OrderHead>().gt(OrderHead.GMT_CREATE, beforeTime));
                if (!CollectionUtils.isEmpty(orderHeadList)) {
                    List<Integer> userIds = orderHeadList.stream().map(OrderHead::getUserId).distinct().collect(Collectors.toList());
                    list = selectByIds(userIds);
                }
                break;
            case "2":
                list = getMonetary(param.getDissipate(), param.getMonetary());
                break;
            case "3":
                list = getFrequency(param.getDissipate(), param.getFrequency());
                break;
            case "4":
                list = getUseCouponCount(param.getDissipate(), param.getUseCouponCount());
                break;
            default:
                throw new ServiceException("type：查询类型不存在");
        }

        //塞入邀请人信息
        List<UserInfoResult> userInfoResults = ObjectConvertUtil.convertList(list, UserInfoResult.class);
        if (!CollectionUtils.isEmpty(userInfoResults)) {
            List<Integer> ids = userInfoResults.stream().map(UserInfoResult::getId).collect(Collectors.toList());
            List<UserInviteRelation> userInviteRelationList = selectAllInviteRelation(ids);
            List<UserInviteRelation> userInviteList = Lists.newArrayList();
            for (UserInfoResult userInfoResult : userInfoResults) {
                if (!CollectionUtils.isEmpty(userInviteRelationList)) {
                    for (UserInviteRelation userInviteRelation : userInviteRelationList) {
                        if (userInviteRelation.getParentId().equals(userInfoResult.getId())) {
                            userInviteList.add(userInviteRelation);
                        }
                    }
                    userInfoResult.setInviteCount(userInviteList.size());
                    userInviteList.clear();
                }
            }
        }
        return userInfoResults;
    }

    /**
     * 数据大屏之全国用户数
     *
     * @return
     */
    @Override
    public DataScreenUserResult statUser() {
        DataScreenUserResult result = new DataScreenUserResult();
        //查询总用户数
        int totalCount = baseMapper.selectCount(new QueryWrapper<UserInfo>()
                .eq(UserInfo.STATUS, 1)
                .eq(UserInfo.IS_DEL, 1));
        result.setTotalCount(totalCount);
        //查询活跃用户
        int activeCount = userLoginHistoryService.getActiveCount();
        result.setActiveCount(10000 + activeCount);
        //查询付费用户
        int orderCount = orderHeadService.orderPayUserCount();
        result.setOrderCount(orderCount);
        return result;
    }

    private List<UserInviteRelation> selectAllInviteRelation(List<Integer> ids) {

        return userInviteRelationService.list(new QueryWrapper<UserInviteRelation>()
                .in(UserInviteRelation.PARENT_ID, ids)
                .notIn(UserInviteRelation.TYPE, Lists.newArrayList(2)));
    }

    /**
     * 根据用户
     *
     * @param userIds 用户Id集合
     * @return 返回用户集合
     */
    private List<UserInfo> selectByIds(List<Integer> userIds) {

        return baseMapper.selectList(new QueryWrapper<UserInfo>().eq(UserInfo.IS_DEL, 1)
                .eq(UserInfo.STATUS, 1).in(UserInfo.ID, userIds));
    }

    /**
     * 最近消费金额用户
     *
     * @param dissipate 时间戳
     * @param monetary  消费金额（分）
     * @return
     */
    private List<UserInfo> getMonetary(Long dissipate, String monetary) {

        //时间戳转换
        if (dissipate == null || dissipate == 0) {
            throw new ServiceException("最近消费时间不能为空");
        }
        String beforeTime = DateUtils.stampToYMDStr(dissipate);
        //金额区间
        if (Arguments.strIsNull(monetary)) {
            throw new ServiceException("最近消费金额不能为空!");
        }
        int startFee = 0;
        int endFee = 0;
        if (monetary.contains("-")) {
            String[] split = monetary.split("-");
            startFee = Integer.parseInt(split[0].trim());
            endFee = Integer.parseInt(split[1].trim());
            if (endFee == 0) {
                endFee = -1;
            }
        } else {
            endFee = Integer.parseInt(monetary);
        }
        QueryWrapper<OrderHead> queryWrapper = new QueryWrapper<OrderHead>().gt(OrderHead.GMT_CREATE, beforeTime)
                .groupBy(OrderHead.USER_ID);
        if (endFee == -1) {
            queryWrapper.having("sum(snapshot_total_fee) > {0}", startFee);
        } else {
            queryWrapper.having("sum(snapshot_total_fee) between {0} and {1}", startFee, endFee);
        }
        //得到结果的订单列表
        List<OrderHead> orderHeadList = orderHeadService.list(queryWrapper);

        return convertUserInfo(orderHeadList);
    }

    /**
     * 由订单列表筛选出账户列表
     *
     * @param orderHeadList 订单列表
     * @return
     */
    private List<UserInfo> convertUserInfo(List<OrderHead> orderHeadList) {
        List<UserInfo> userInfoList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(orderHeadList)) {
            List<Integer> userIds = orderHeadList.stream().map(OrderHead::getUserId).distinct().collect(Collectors.toList());
            userInfoList = selectByIds(userIds);
        }
        return userInfoList;
    }


    /**
     * 最近消费频率用户
     *
     * @param dissipate 时间戳
     * @param frequency 频率，单位次
     * @return
     */
    private List<UserInfo> getFrequency(Long dissipate, String frequency) {
        List<UserInfo> userInfoList = Lists.newArrayList();
        //时间戳转换
        if (dissipate == null || dissipate == 0) {
            throw new ServiceException("最近消费时间不能为空");
        }
        String beforeTime = DateUtils.stampToYMDStr(dissipate);
        if (Arguments.strIsNull(frequency)) {
            throw new ServiceException("最近消费频率不能为空");
        }
        int startCount = 0;
        int endCount = 0;
        if (frequency.contains("-")) {
            String[] split = frequency.split("-");
            startCount = Integer.valueOf(split[0].trim());
            endCount = Integer.valueOf(split[1].trim());
            if (endCount == 0) {
                endCount = -1;
            }
        } else {
            endCount = Integer.valueOf(frequency.trim());
        }
        QueryWrapper<OrderHead> queryWrapper = new QueryWrapper<OrderHead>()
                .eq(OrderHead.STATUS, OrderStatus.postCheckOut)
                .gt(OrderHead.GMT_CREATE, beforeTime)
                .groupBy(OrderHead.USER_ID);
        if (endCount == -1) {
            queryWrapper.having("count(order_no) > {0}", startCount);
        } else {
            queryWrapper.having("count(order_no) between {0} and {1}", startCount, endCount);
        }
        //得到结果的订单列表
        List<OrderHead> orderHeadList = orderHeadService.list(queryWrapper);


        return convertUserInfo(orderHeadList);
    }

    /**
     * 最近使用优惠券用户
     *
     * @param dissipate      最近时间
     * @param useCouponCount 优惠券数量
     * @return
     */
    private List<UserInfo> getUseCouponCount(Long dissipate, String useCouponCount) {
        if (Arguments.strIsNull(useCouponCount)) {
            throw new ServiceException("最近使用优惠券不能为空");
        }
        int startCouponCount = 0;
        int endCouponCount = 0;
        QueryWrapper<OrderHead> query = null;
        if (useCouponCount.contains("-")) {
            String[] split = useCouponCount.split("-");
            startCouponCount = Integer.valueOf(split[0].trim());
            endCouponCount = Integer.valueOf(split[1].trim());
            query = new QueryWrapper<OrderHead>()
                    .eq(OrderHead.STATUS, OrderStatus.postCheckOut)
                    .isNotNull(OrderHead.USER_COUPON_ID)
                    .ne(OrderHead.USER_COUPON_ID, 0)
                    .groupBy(OrderHead.USER_ID);
            if (endCouponCount == 0) {
                query.having("count(user_coupon_id) > {0}", startCouponCount);
            } else {
                query.having("count(user_coupon_id) between {0} and {1}", startCouponCount, endCouponCount);
            }

        } else {
            endCouponCount = Integer.parseInt(useCouponCount.trim());
            query = new QueryWrapper<OrderHead>()
                    .eq(OrderHead.STATUS, OrderStatus.postCheckOut)
                    .groupBy(OrderHead.USER_ID)
                    .having("count(user_coupon_id) between {0} and {1}", startCouponCount, endCouponCount);
        }
        List<OrderHead> list = orderHeadService.list(query);

        return convertUserInfo(list);
    }


}
